package edu.scau.divineplace.service;

import cn.hutool.core.util.PageUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import edu.scau.divineplace.entity.dos.CommentForumDO;
import edu.scau.divineplace.entity.dos.LikeDO;
import edu.scau.divineplace.entity.dos.UserDO;
import edu.scau.divineplace.entity.enums.BaseEnum;
import edu.scau.divineplace.entity.enums.CommentTargetTypeEnum;
import edu.scau.divineplace.entity.enums.IsReadEnum;
import edu.scau.divineplace.entity.enums.LikeTargetTypeEnum;
import edu.scau.divineplace.entity.query.CommentForumQuery;
import edu.scau.divineplace.entity.query.PageQuery;
import edu.scau.divineplace.entity.vo.commentforum.CommentForumNode;
import edu.scau.divineplace.entity.vo.commentforum.CommentForumChildNode;
import edu.scau.divineplace.entity.vo.commentforum.CommentForumVO;
import edu.scau.divineplace.util.PageQueryUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: x1aolone
 * @Date: 2020/12/11 15:48
 */
@Service
public class CommentForumService {

    @Autowired
    private ImportMapperService importMapperService;

    /**
     * 通过内容id、内容类型、用户id获取内容的楼层评论
     * @param contentId 内容id
     * @param commentTargetType 内容类型，人物/日志
     * @param userId 用户id，可为null
     * @param pageQuery
     * @return
     */
    public List<CommentForumVO> list(Long contentId, Integer commentTargetType, Long userId, PageQuery pageQuery){
        PageQueryUtil.fillAllIfAbsent(pageQuery);
        Preconditions.checkArgument(BaseEnum.isExist(CommentTargetTypeEnum.class, commentTargetType));
        // 按分页拿出层级的评论
        Page<CommentForumDO> commentForumPage = new Page<>(pageQuery.getCurrentPage(), pageQuery.getPageSize());
        LambdaQueryWrapper<CommentForumDO> query = Wrappers.<CommentForumDO>lambdaQuery()
                .eq(CommentForumDO::getCommentTargetId, contentId)
                .eq(CommentForumDO::getCommentTargetType, commentTargetType)
                .eq(CommentForumDO::getParentId, CommentForumNode.ROOT_NODE_PARENT_ID)
                .orderByAsc(CommentForumDO::getCreateTime)
                .orderByAsc(CommentForumDO::getUpdateTime);
        commentForumPage = importMapperService.commentForumMapper.selectPage(commentForumPage, query);
        List<CommentForumVO> VOS = Lists.newArrayList();
        for (CommentForumDO DO : commentForumPage.getRecords()) {
            Long parentId = DO.getId();
            CommentForumVO VO = CommentForumVO.builder()
                    .info(newCommentForumNode(DO, userId))
                    .children(findChildren(parentId, userId))
                    .build();
            VOS.add(VO);
        }
        return VOS;
    }

    /**
     * 寻找id为parentId的子回复并组装好信息
     * @param parentId
     * @return
     */
    public List<CommentForumChildNode> findChildren (Long parentId, Long userId) {
        LambdaQueryWrapper<CommentForumDO> query = Wrappers.<CommentForumDO>lambdaQuery()
                .eq(CommentForumDO::getParentId, parentId)
                .orderByAsc(CommentForumDO::getCreateTime)
                .orderByAsc(CommentForumDO::getUpdateTime);
        List<CommentForumDO> DOS = importMapperService.commentForumMapper.selectList(query);
        List<CommentForumChildNode> children = Lists.newArrayList();
        // 拼装信息
        for (CommentForumDO DO : DOS) {
            CommentForumChildNode child = new CommentForumChildNode();
            child.setInfo(newCommentForumNode(DO, userId));
            boolean haveReply = DO.getReplyCommentForumId() != null
                    && DO.getReplyCommentForumId() != 0
                    && !DO.getReplyCommentForumId().equals(parentId);
            if (haveReply) {
                // 对于每一个回复，如果有回复对象，需要组装回复对象的信息
                Long replyId = DO.getReplyCommentForumId();
                CommentForumDO repliedDO = importMapperService.commentForumMapper.selectById(replyId);
                child.setRepliedComment(newCommentForumNode(repliedDO, userId));
            }
            children.add(child);
        }
        return children;
    }

    public CommentForumNode newCommentForumNode (CommentForumDO DO, Long userId) {
        // 查一下发表的用户信息
        UserDO userDO = importMapperService.userMapper.selectById(DO.getUserId());
        // 查一下点赞该评论的人数
        LambdaQueryWrapper<LikeDO> likeQuery = Wrappers.<LikeDO>lambdaQuery()
                .eq(LikeDO::getLikeTargetType, LikeTargetTypeEnum.COMMENT_FORUM.getType())
                .eq(LikeDO::getLikeTargetId, DO.getId());
        Integer likeNum = importMapperService.likeMapper.selectCount(likeQuery);
        // 如果已登录，查一下本人有没有点赞该评论
        Boolean isLiked = null;
        if (userId != null) {
            likeQuery.eq(LikeDO::getUserId, userId);
            Integer isLikeNum = importMapperService.likeMapper.selectCount(likeQuery);
            isLiked = isLikeNum > 0;
        }
        // 组装结点
        CommentForumNode node = CommentForumNode.builder()
                .id(DO.getId())
                .comment(DO.getComment())
                .createTime(DO.getCreateTime())
                .user(userDO)
                .likeNum(likeNum)
                .isLiked(isLiked)
                .build();
        return node;
    }

    /**
     * 添加新的CommentForum
     * @param query
     */
    public void add(CommentForumQuery query){
        CommentTargetTypeEnum commentTargetType = BaseEnum.typeOf(CommentTargetTypeEnum.class, query.getCommentTargetType());
        Preconditions.checkNotNull(commentTargetType);
        CommentForumDO DO = new CommentForumDO();
        DO.setParentId(query.getParentId());
        DO.setReplyCommentForumId(query.getReplyCommentForumId());
        DO.setReplyUserId(query.getReplyUserId());
        DO.setUserId(query.getUserId());
        DO.setCommentTargetType(commentTargetType);
        DO.setCommentTargetId(query.getCommentTargetId());
        DO.setComment(query.getComment());
        importMapperService.commentForumMapper.insert(DO);
    }

}
